home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Modules / linuxaudiodev.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  10.5 KB  |  467 lines

  1. /* Hey Emacs, this is -*-C-*- 
  2.  ******************************************************************************
  3.  * linuxaudiodev.c -- Linux audio device for python.
  4.  * 
  5.  * Author          : Peter Bosch
  6.  * Created On      : Thu Mar  2 21:10:33 2000
  7.  * Last Modified By: Peter Bosch
  8.  * Last Modified On: Fri Mar 24 11:27:00 2000
  9.  * Status          : Unknown, Use with caution!
  10.  * 
  11.  * Unless other notices are present in any part of this file
  12.  * explicitly claiming copyrights for other people and/or 
  13.  * organizations, the contents of this file is fully copyright 
  14.  * (C) 2000 Peter Bosch, all rights reserved.
  15.  ******************************************************************************
  16.  */
  17.  
  18. #include "Python.h"
  19. #include "structmember.h"
  20.  
  21. #ifdef HAVE_UNISTD_H
  22. #include <unistd.h>
  23. #endif
  24.  
  25. #ifdef HAVE_FCNTL_H
  26. #include <fcntl.h>
  27. #endif
  28.  
  29. #include <sys/ioctl.h>
  30. #include <linux/soundcard.h>
  31.  
  32. typedef unsigned long uint32_t;
  33.  
  34. typedef struct {
  35.   PyObject_HEAD;
  36.   int        x_fd;        /* The open file */
  37.   int        x_icount;    /* Input count */
  38.   int        x_ocount;    /* Output count */
  39.   uint32_t    x_afmts;    /* Supported audio formats */
  40. } lad_t;
  41.  
  42. static struct {
  43.   int        a_bps;
  44.   uint32_t    a_fmt;
  45. } audio_types[] = {
  46.   {  8,     AFMT_MU_LAW },
  47.   {  8,        AFMT_U8 },
  48.   {  8,     AFMT_S8 },
  49.   { 16,     AFMT_U16_BE },
  50.   { 16,     AFMT_U16_LE },
  51.   { 16,     AFMT_S16_BE },
  52.   { 16,     AFMT_S16_LE },
  53. };
  54.  
  55.  
  56. staticforward PyTypeObject Ladtype;
  57.  
  58. static PyObject *LinuxAudioError;
  59.  
  60. static lad_t *
  61. newladobject(PyObject *arg)
  62. {
  63.   lad_t *xp;
  64.   int fd, afmts, imode;
  65.   char *mode;
  66.   char *basedev;
  67.   char *ctldev;
  68.   char *opendev;
  69.  
  70.   /* Check arg for r/w/rw */
  71.   if (!PyArg_ParseTuple(arg, "s", &mode)) return NULL;
  72.   if (strcmp(mode, "r") == 0)
  73.     imode = 0;
  74.   else if (strcmp(mode, "w") == 0)
  75.     imode = 1;
  76.   else {
  77.     PyErr_SetString(LinuxAudioError, "Mode should be one of 'r', or 'w'");
  78.     return NULL;
  79.   }
  80.     
  81.   /* Open the correct device.  The base device name comes from the
  82.    * AUDIODEV environment variable first, then /dev/audio.  The
  83.    * control device tacks "ctl" onto the base device name.
  84.    */
  85.   basedev = getenv("AUDIODEV");
  86.   if (!basedev)
  87.     basedev = "/dev/dsp";
  88.  
  89.   if ((fd = open(basedev, imode)) < 0) {
  90.     PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev);
  91.     return NULL;
  92.   }
  93.  
  94.   if (imode) {
  95.     if (ioctl(fd, SNDCTL_DSP_NONBLOCK, NULL) < 0) {
  96.       PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev);
  97.       return NULL;
  98.     }
  99.   }
  100.  
  101.   if (ioctl(fd, SNDCTL_DSP_GETFMTS, &afmts) < 0) {
  102.     PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev);
  103.     return NULL;
  104.   }
  105.  
  106.   /* Create and initialize the object */
  107.   if ((xp = PyObject_New(lad_t, &Ladtype)) == NULL) {
  108.     close(fd);
  109.     return NULL;
  110.   }
  111.   xp->x_fd     = fd;
  112.   xp->x_icount = xp->x_ocount = 0;
  113.   xp->x_afmts  = afmts;
  114.   return xp;
  115. }
  116.  
  117. static void
  118. lad_dealloc(lad_t *xp)
  119. {
  120.   close(xp->x_fd);
  121.   PyObject_Del(xp);
  122. }
  123.  
  124. static PyObject *
  125. lad_read(lad_t *self, PyObject *args)
  126. {
  127.   int size, count;
  128.   char *cp;
  129.   PyObject *rv;
  130.     
  131.   if (!PyArg_ParseTuple(args, "i", &size)) return NULL;
  132.   rv = PyString_FromStringAndSize(NULL, size);
  133.   if (rv == NULL) return NULL;
  134.  
  135.   if (!(cp = PyString_AsString(rv))) {
  136.     Py_DECREF(rv);
  137.     return NULL;
  138.   }
  139.  
  140.   if ((count = read(self->x_fd, cp, size)) < 0) {
  141.     PyErr_SetFromErrno(LinuxAudioError);
  142.     Py_DECREF(rv);
  143.     return NULL;
  144.   }
  145.  
  146.   self->x_icount += count;
  147.   return rv;
  148. }
  149.  
  150. static PyObject *
  151. lad_write(lad_t *self, PyObject *args)
  152. {
  153.   char *cp;
  154.   int rv, size;
  155.     
  156.   if (!PyArg_ParseTuple(args, "s#", &cp, &size)) return NULL;
  157.  
  158.   while (size > 0) {
  159.     if ((rv = write(self->x_fd, cp, size)) < 0) {
  160.       PyErr_SetFromErrno(LinuxAudioError);
  161.       return NULL;
  162.     }
  163.     self->x_ocount += rv;
  164.     size           -= rv;
  165.     cp             += rv;
  166.   }
  167.   Py_INCREF(Py_None);
  168.   return Py_None;
  169. }
  170.  
  171. static PyObject *
  172. lad_close(lad_t *self, PyObject *args)
  173. {
  174.   if (!PyArg_ParseTuple(args, "")) return NULL;
  175.   if (self->x_fd >= 0) {
  176.     close(self->x_fd);
  177.     self->x_fd = -1;
  178.   }
  179.   Py_INCREF(Py_None);
  180.   return Py_None;
  181. }
  182.  
  183. static PyObject *
  184. lad_fileno(lad_t *self, PyObject *args)
  185. {
  186.   if (!PyArg_ParseTuple(args, "")) return NULL;
  187.   return PyInt_FromLong(self->x_fd);
  188. }
  189.  
  190. static PyObject *
  191. lad_setparameters(lad_t *self, PyObject *args)
  192. {
  193.   int rate, ssize, nchannels, stereo, n, fmt;
  194.  
  195.   if (!PyArg_ParseTuple(args, "iiii", &rate, &ssize, &nchannels, &fmt))
  196.     return NULL;
  197.   
  198.   if (rate < 0 || ssize < 0 || (nchannels != 1 && nchannels != 2)) {
  199.     PyErr_SetFromErrno(LinuxAudioError);
  200.     return NULL;
  201.   }
  202.  
  203.   if (ioctl(self->x_fd, SOUND_PCM_WRITE_RATE, &rate) < 0) {
  204.     PyErr_SetFromErrno(LinuxAudioError);
  205.     return NULL;
  206.   }
  207.  
  208.   if (ioctl(self->x_fd, SNDCTL_DSP_SAMPLESIZE, &ssize) < 0) {
  209.     PyErr_SetFromErrno(LinuxAudioError);
  210.     return NULL;
  211.   }
  212.  
  213.   stereo = (nchannels == 1)? 0: (nchannels == 2)? 1: -1;
  214.   if (ioctl(self->x_fd, SNDCTL_DSP_STEREO, &stereo) < 0) {
  215.     PyErr_SetFromErrno(LinuxAudioError);
  216.     return NULL;
  217.   }
  218.  
  219.   for (n = 0; n != sizeof(audio_types) / sizeof(audio_types[0]); n++)
  220.     if (fmt == audio_types[n].a_fmt)
  221.       break;
  222.  
  223.   if (n == sizeof(audio_types) / sizeof(audio_types[0]) ||
  224.       audio_types[n].a_bps != ssize ||
  225.       (self->x_afmts & audio_types[n].a_fmt) == 0) {
  226.     PyErr_SetFromErrno(LinuxAudioError);
  227.     return NULL;
  228.   }
  229.  
  230.   if (ioctl(self->x_fd, SNDCTL_DSP_SETFMT, &audio_types[n].a_fmt) < 0) {
  231.     PyErr_SetFromErrno(LinuxAudioError);
  232.     return NULL;
  233.   }
  234.   
  235.   Py_INCREF(Py_None);
  236.   return Py_None;
  237. }
  238.  
  239. static int
  240. _ssize(lad_t *self, int *nchannels, int *ssize)
  241. {
  242.   int fmt;
  243.  
  244.   fmt = 0;
  245.   if (ioctl(self->x_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) 
  246.     return -errno;
  247.  
  248.   switch (fmt) {
  249.   case AFMT_MU_LAW:
  250.   case AFMT_A_LAW:
  251.   case AFMT_U8:
  252.   case AFMT_S8:
  253.     *ssize = sizeof(char);
  254.     break;
  255.   case AFMT_S16_LE:
  256.   case AFMT_S16_BE:
  257.   case AFMT_U16_LE:
  258.   case AFMT_U16_BE:
  259.     *ssize = sizeof(short);
  260.     break;
  261.   case AFMT_MPEG:
  262.   case AFMT_IMA_ADPCM:
  263.   default:
  264.     return -EOPNOTSUPP;
  265.   }
  266.  
  267.   *nchannels = 0;
  268.   if (ioctl(self->x_fd, SNDCTL_DSP_CHANNELS, nchannels) < 0)
  269.     return -errno;
  270.   return 0;
  271. }
  272.  
  273.  
  274. /* bufsize returns the size of the hardware audio buffer in number 
  275.  of samples */
  276. static PyObject *
  277. lad_bufsize(lad_t *self, PyObject *args)
  278. {
  279.   audio_buf_info ai;
  280.   int nchannels, ssize;
  281.  
  282.   if (!PyArg_ParseTuple(args, "")) return NULL;
  283.  
  284.   if (_ssize(self, &nchannels, &ssize) < 0) {
  285.     PyErr_SetFromErrno(LinuxAudioError);
  286.     return NULL;
  287.   }
  288.  
  289.   if (ioctl(self->x_fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
  290.     PyErr_SetFromErrno(LinuxAudioError);
  291.     return NULL;
  292.   }
  293.  
  294.   return PyInt_FromLong((ai.fragstotal * ai.fragsize) / (nchannels * ssize));
  295. }
  296.  
  297. /* obufcount returns the number of samples that are available in the 
  298.    hardware for playing */
  299. static PyObject *
  300. lad_obufcount(lad_t *self, PyObject *args)
  301. {
  302.   audio_buf_info ai;
  303.   int nchannels, ssize;
  304.  
  305.   if (!PyArg_ParseTuple(args, "")) return NULL;
  306.  
  307.   if (_ssize(self, &nchannels, &ssize) < 0) {
  308.     PyErr_SetFromErrno(LinuxAudioError);
  309.     return NULL;
  310.   }
  311.  
  312.   if (ioctl(self->x_fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
  313.     PyErr_SetFromErrno(LinuxAudioError);
  314.     return NULL;
  315.   }
  316.  
  317.   return PyInt_FromLong((ai.fragstotal * ai.fragsize - ai.bytes) / 
  318.             (ssize * nchannels));
  319. }
  320.  
  321. /* obufcount returns the number of samples that can be played without
  322.  blocking */
  323. static PyObject *
  324. lad_obuffree(lad_t *self, PyObject *args)
  325. {
  326.   audio_buf_info ai;
  327.   int nchannels, ssize;
  328.  
  329.   if (!PyArg_ParseTuple(args, "")) return NULL;
  330.  
  331.   if (_ssize(self, &nchannels, &ssize) < 0) {
  332.     PyErr_SetFromErrno(LinuxAudioError);
  333.     return NULL;
  334.   }
  335.  
  336.   if (ioctl(self->x_fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
  337.     PyErr_SetFromErrno(LinuxAudioError);
  338.     return NULL;
  339.   }
  340.  
  341.   return PyInt_FromLong(ai.bytes / (ssize * nchannels));
  342. }
  343.  
  344. /* Flush the device */
  345. static PyObject *
  346. lad_flush(lad_t *self, PyObject *args)
  347. {
  348.   if (!PyArg_ParseTuple(args, "")) return NULL;
  349.  
  350.   if (ioctl(self->x_fd, SNDCTL_DSP_SYNC, NULL) < 0) {
  351.     PyErr_SetFromErrno(LinuxAudioError);
  352.     return NULL;
  353.   }
  354.  
  355.   Py_INCREF(Py_None);
  356.   return Py_None;
  357. }
  358.  
  359. static PyMethodDef lad_methods[] = {
  360.   { "read",        (PyCFunction)lad_read, 1 },
  361.   { "write",        (PyCFunction)lad_write, 1 },
  362.   { "setparameters",    (PyCFunction)lad_setparameters, 1 },
  363.   { "bufsize",        (PyCFunction)lad_bufsize, 1 },
  364.   { "obufcount",    (PyCFunction)lad_obufcount, 1 },
  365.   { "obuffree",        (PyCFunction)lad_obuffree, 1 },
  366.   { "flush",        (PyCFunction)lad_flush, 1 },
  367.   { "close",        (PyCFunction)lad_close, 1 },
  368.   { "fileno",         (PyCFunction)lad_fileno, 1 },
  369.   { NULL,        NULL}        /* sentinel */
  370. };
  371.  
  372. static PyObject *
  373. lad_getattr(lad_t *xp, char *name)
  374. {
  375.   return Py_FindMethod(lad_methods, (PyObject *)xp, name);
  376. }
  377.  
  378. static PyTypeObject Ladtype = {
  379.   PyObject_HEAD_INIT(&PyType_Type)
  380.   0,                /*ob_size*/
  381.   "linux_audio_device",        /*tp_name*/
  382.   sizeof(lad_t),        /*tp_size*/
  383.   0,                /*tp_itemsize*/
  384.   /* methods */
  385.   (destructor)lad_dealloc,    /*tp_dealloc*/
  386.   0,                /*tp_print*/
  387.   (getattrfunc)lad_getattr,    /*tp_getattr*/
  388.   0,                /*tp_setattr*/
  389.   0,                /*tp_compare*/
  390.   0,                /*tp_repr*/
  391. };
  392.  
  393. static PyObject *
  394. ladopen(PyObject *self, PyObject *args)
  395. {
  396.   return (PyObject *)newladobject(args);
  397. }
  398.  
  399. static PyMethodDef linuxaudiodev_methods[] = {
  400.   { "open", ladopen, 1 },
  401.   { 0, 0 },
  402. };
  403.  
  404. static int
  405. ins(PyObject *d, char *symbol, long value)
  406. {
  407.   PyObject* v = PyInt_FromLong(value);
  408.   if (!v || PyDict_SetItemString(d, symbol, v) < 0)
  409.     return -1;                   /* triggers fatal error */
  410.  
  411.   Py_DECREF(v);
  412.   return 0;
  413. }
  414. void
  415. initlinuxaudiodev()
  416. {
  417.   PyObject *m, *d, *x;
  418.   
  419.   m = Py_InitModule("linuxaudiodev", linuxaudiodev_methods);
  420.   d = PyModule_GetDict(m);
  421.  
  422.   LinuxAudioError = PyErr_NewException("linuxaudiodev.error", NULL, NULL);
  423.   if (LinuxAudioError)
  424.     PyDict_SetItemString(d, "error", LinuxAudioError);
  425.  
  426.   x = PyInt_FromLong((long) AFMT_MU_LAW);
  427.   if (x == NULL || PyDict_SetItemString(d, "AFMT_MU_LAW", x) < 0)
  428.     goto error;
  429.   Py_DECREF(x);
  430.  
  431.   x = PyInt_FromLong((long) AFMT_U8);
  432.   if (x == NULL || PyDict_SetItemString(d, "AFMT_U8", x) < 0)
  433.     goto error;
  434.   Py_DECREF(x);
  435.  
  436.   x = PyInt_FromLong((long) AFMT_S8);
  437.   if (x == NULL || PyDict_SetItemString(d, "AFMT_S8", x) < 0)
  438.     goto error;
  439.   Py_DECREF(x);
  440.  
  441.   x = PyInt_FromLong((long) AFMT_U16_BE);
  442.   if (x == NULL || PyDict_SetItemString(d, "AFMT_U16_BE", x) < 0)
  443.     goto error;
  444.   Py_DECREF(x);
  445.  
  446.   x = PyInt_FromLong((long) AFMT_U16_LE);
  447.   if (x == NULL || PyDict_SetItemString(d, "AFMT_U16_LE", x) < 0)
  448.     goto error;
  449.   Py_DECREF(x);
  450.  
  451.   x = PyInt_FromLong((long) AFMT_S16_BE);
  452.   if (x == NULL || PyDict_SetItemString(d, "AFMT_S16_BE", x) < 0)
  453.     goto error;
  454.   Py_DECREF(x);
  455.  
  456.   x = PyInt_FromLong((long) AFMT_S16_LE);
  457.   if (x == NULL || PyDict_SetItemString(d, "AFMT_S16_LE", x) < 0)
  458.     goto error;
  459.   Py_DECREF(x);
  460.  
  461.   /* Check for errors */
  462.   if (PyErr_Occurred()) {
  463.   error:
  464.     Py_FatalError("can't initialize module linuxaudiodev");
  465.   }
  466. }
  467.